/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package SemanticoPacote;

import compilador_full.TabelaSimbolos;

/**
 *
 * @author Fernanda
 */
public class AnaliseSemantica {

    //private Hashtable<Integer, String> auxiliar = new Hashtable<Integer, String>();
    private declaracaoConstantes constante = new declaracaoConstantes();
    private declaraVariaveis variaveis = new declaraVariaveis();
    private declaracaoMetodos declaraMetodos = new declaracaoMetodos();
    private declaracaoMetodosVoid declaraMVoid = new declaracaoMetodosVoid();
    private declaracaoStructs declaraStruct = new declaracaoStructs();
    private int indiceConstante = 0;
    private int indiceMetodo = 0;
    private int indiceMetodoVoid = 0;
    // private int indiceStruct = 0;

    public AnaliseSemantica() {
    }

    public void startAnalise(TabelaSimbolos tabelasimbolos) {
        declaracaoMetodoMain metodoMain = new declaracaoMetodoMain();
        declaraVariaveis declaraVar = new declaraVariaveis();

        tabelasimbolos.preencheArray(); //gerando estrutura que guarda informações para semantica
        tabelasimbolos.ZeraLookahead(); //reiniciando
        tabelasimbolos.imprimeTodosTokens();

        // Verifica bibliotecas
        while (tabelasimbolos.getLookahead().equals("include")) {
            while (!tabelasimbolos.getLookahead().equals(">")) {
                tabelasimbolos.soConsome();
            }
             tabelasimbolos.soConsome();//consome o >
        }

        // Verifica constantes
        while (tabelasimbolos.getLookahead().equals("const")) {
            constante.semanticaConstantes(tabelasimbolos, indiceConstante++);
        }

        //verifica delcaração de struct, variaveis e ponteiros que começam por typedef, struct ou é do tipo "tipos"
        while (tabelasimbolos.getLookahead().equals("typedef") || tabelasimbolos.getLookahead().equals("struct") || (apenasCompara(tabelasimbolos) && (!tabelasimbolos.superLookahead(2).equals("(")))) {

            if (tabelasimbolos.getLookahead().equals("struct")) {
                //declaraStructs
                declaraStruct.declaraStructs(tabelasimbolos);
            } else if (tabelasimbolos.getLookahead().equals("typedef")) {
                if (tabelasimbolos.superLookahead(1).equals("struct")) {
                    //declaraStructs();
                    declaraStruct.declaraStructs(tabelasimbolos);
                } else if (isDentroDeTipo(tabelasimbolos, 1)) {

                    //declaraVariaveis();
                    declaraVar.declaraVariaveis(tabelasimbolos, "global");

                }
            } else if (apenasCompara(tabelasimbolos)) {//se look estah dentro de tipos
                if (tabelasimbolos.superTipo(1).equals("identificador") && !tabelasimbolos.superLookahead(2).equals("(") || tabelasimbolos.superLookahead(1).equals("*")) {
                    //declaraVariaveis();
                    declaraVar.declaraVariaveis(tabelasimbolos, "global");
                }
            }

        }
            while (apenasCompara(tabelasimbolos) || (tabelasimbolos.getLookahead().equals("void") && !tabelasimbolos.superLookahead(1).equals("main"))) {

                if (!tabelasimbolos.getLookahead().equals("void") &&
                        ((tabelasimbolos.superLookahead(1).equals("*") && tabelasimbolos.superTipo(2).equals("identificador") && tabelasimbolos.superLookahead(3).equals("(")) ||
                        (tabelasimbolos.superTipo(1).equals("identificador") && tabelasimbolos.superLookahead(2).equals("(")))) {
                    declaraMetodos.declaraMetodos(tabelasimbolos, indiceMetodo++);
                } else if (tabelasimbolos.getLookahead().equals("void") && tabelasimbolos.superTipo(1).equals("identificador")) {
                    //declaracaoMetodosVoid(tabelasimbolos);
                    declaraMVoid.declaraMetodosVoid(tabelasimbolos, indiceMetodoVoid++);
                } else {
                    break;
                }
            }

            //o escopo de qualquer variavel ou metodo declarado dentro da main = main
            metodoMain.declaracaoMetodoMain(tabelasimbolos);
        
    } 

    public static boolean apenasCompara(TabelaSimbolos tabelaSimbolos) {

        String verifica = tabelaSimbolos.getLookahead();

        if (verifica.equals("int") || verifica.equals("float") ||
                verifica.equals("boolean") || verifica.equals("char")) {
            return true;
        } else if (tabelaSimbolos.getTipo().equals("identificador")) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean isDentroDeTipo(TabelaSimbolos tabelaSimbolos, int ponteiro) {
        String verifica = tabelaSimbolos.superLookahead(ponteiro);

        if (verifica.equals("int") || verifica.equals("float") ||
                verifica.equals("boolean") || verifica.equals("char")) {
            //tabelaSimbolos.reconhecer(verifica);
            return true;
        } else {
            return false;
        }
    }

    public void ina(int i ){
        for(i = 0;i<5;i++){

        }
    }
}
